/*
 *  LibNoPoll: A websocket library
 *  Copyright (C) 2017 Advanced Software Production Line, S.L.
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public License
 *  as published by the Free Software Foundation; either version 2.1
 *  of the License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this program; if not, write to the Free
 *  Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 *  02111-1307 USA
 *
 *  You may find a copy of the license under this software is released
 *  at COPYING file. This is LGPL software: you are welcome to develop
 *  proprietary applications using this library without any royalty or
 *  fee but returning back any change, improvement or addition in the
 *  form of source code, project image, documentation patches, etc.
 *
 *  For commercial support on build Websocket enabled solutions
 *  contact us:
 *
 *      Postal address:
 *         Advanced Software Production Line, S.L.
 *         Av. Juan Carlos I, Nº13, 2ºC
 *         Alcalá de Henares 28806 Madrid
 *         Spain
 *
 *      Email address:
 *         info@aspl.es - http://www.aspl.es/nopoll
 */
#ifndef __NOPOLL_PRIVATE_H__
#define __NOPOLL_PRIVATE_H__

//#include <openssl/bio.h>
//#include <openssl/evp.h>
//#include <openssl/objects.h>
//#include <openssl/x509v3.h>
//#include <openssl/ssl.h>
//#include <openssl/err.h>
//#include <openssl/opensslv.h>

#include "nopoll_handlers.h"
//#define OPENSSL  1

typedef struct _noPollCertificate {

    char *serverName;
    char *certificateFile;
    char *privateKey;
    char *optionalChainFile;

} noPollCertificate;

struct _noPollCtx {
    /**
     * @internal Controls logs output..
     */
    /* context reference counting */
    noPollRead read_handler;
    noPollRead write_handler;
    void *user_data;
    int refs;

    /* console log */
    nopoll_bool not_executed;
    nopoll_bool debug_enabled;

    /* colored log */
    nopoll_bool not_executed_color;
    nopoll_bool debug_color_enabled;

    nopoll_bool keep_looping;

    /**
     * @internal noPollConn connection timeout.
     */
    long conn_connect_std_timeout;
    /**
     * @internal Basic fake support for protocol version, by
     * default: 13, due to RFC6455 standard
     */
    int protocol_version;
    /* mutex */
    noPollPtr ref_mutex;

    /* log handling */
    noPollLogHandler log_handler;
    noPollPtr log_user_data;
};

struct _noPollConn {
    /**
     * @internal Connection id.
     */
    int id;

    /**
     * @internal The context associated to this connection.
     */
    noPollCtx *ctx;

    /**
     * @internal This is the actual socket handler associated to
     * the noPollConn object.
     */
    NOPOLL_SOCKET session;
    /**
     * @internal Flag to signal this connection has finished its
     * handshake.
     */
    nopoll_bool handshake_ok;

    /**
     * @internal Current connection receive function.
     */
    noPollRead receive;

    /**
     * @internal Current connection receive function.
     */
    noPollRead send;

    /**
     * @internal The connection role.
     */
    noPollRole role;

    /**
     * @internal Conection host ip location (connecting or listening).
     */
    char *host;

    /**
     * @internal Connection port location (connecting or
     * listening).
     */
    char *port;

    /**
     * @internal Host name requested on the connection.
     */
    char *host_name;

    /**
     * @internal Origin requested on the connection.
     */
    char *origin;

    /**
     * @internal reference to the get url.
     */
    char *get_url;

    /**
     * @internal Reference to protocols requested to be opened on
     * this connection.
     */
    char *protocols;
    /* @internal reference to the protocol that was replied by the server */
    char *accepted_protocol;

    /* close status and reason */
    int peer_close_status;
    char *peer_close_reason;

    /**
     * @internal Reference to the defined on message handling.
     */
    noPollOnMessageHandler on_msg;
    noPollPtr on_msg_data;

    /**
     * @internal Reference to defined on ready handling.
     */
    noPollActionHandler on_ready;
    noPollPtr on_ready_data;

    /**
     * @internal Reference to defined on pong handling.
     */
    noPollActionHandler on_pong;
    noPollPtr on_pong_data;

    /**
     * @internal Reference to the defined on close handling.
     */
    noPollOnCloseHandler on_close;
    noPollPtr on_close_data;

    /* reference to the handshake */
    noPollHandShake *handshake;

    /* reference to a buffer with pending content */
    char *pending_line;

    /**
     * @internal connection reference counting.
     */
    int refs;

    /**
     * @internal References to pending content to be read
     */
    noPollMsg *pending_msg;
    long int pending_diff;
    long int pending_desp;

    /* certificates */
    char *certificate;
    char *private_key;
    char *chain_certificate;

    /* pending buffer */
    char pending_buf[100];
    int pending_buf_bytes;

    /**
     * @internal Support for an user defined pointer.
     */
    noPollPtr hook;

    /**
     * @internal Mutexes
     */
    noPollPtr ref_mutex;
    noPollPtr handshake_mutex;

    /**
     * @internal Variable to track pending bytes from previous
     * read that must be completed.
     */
    noPollMsg *previous_msg;
    /* allows to track if previous message was a fragment to flag
     * next message, even having FIN enabled as a fragment. */
    nopoll_bool previous_was_fragment;

    char *pending_write;
    int pending_write_bytes;
    int pending_write_desp;
    int pending_write_added_header;

    /**
     * @internal Internal reference to the connection options.
     */
    noPollConnOpts *opts;

    /**
     * @internal Reference to the listener in the case this is a
     * connection that was created due to a listener running.
     */
    noPollConn *listener;

    /**
     * @internal Flag to track internal header pending
     */
    nopoll_bool read_pending_header;


    /**** debug values ****/
    /* force stop after header: do not use this, it is just for
       testing purposes */
    nopoll_bool __force_stop_after_header;
};

struct _noPollIoEngine {
    noPollPtr io_object;
    noPollCtx *ctx;
    noPollIoMechCreate create;
    noPollIoMechDestroy destroy;
    noPollIoMechClear clear;
    noPollIoMechWait wait;
    noPollIoMechAddTo add_to;
    noPollIoMechIsSet is_set;
};

struct _noPollMsg {
    nopoll_bool has_fin;
    short op_code;
    nopoll_bool is_masked;

    noPollPtr payload;
    long int payload_size;

    int refs;
    noPollPtr ref_mutex;

    char mask[4];
    int remain_bytes;

    nopoll_bool is_fragment;
    int unmask_desp;
};

struct _noPollHandshake {
    /**
     * @internal Reference to the to the GET url HTTP/1.1 header
     * part.
     */
    nopoll_bool upgrade_websocket;
    nopoll_bool connection_upgrade;
    nopoll_bool received_101;
    char *websocket_key;
    char *websocket_version;
    char *websocket_accept;
    char *expected_accept;

    /* reference to cookie header */
    char *cookie;
};

struct _noPollConnOpts {
    /* If the connection options object should be reused across calls */
    nopoll_bool reuse;

    /* mutex */
    noPollPtr mutex;
    int refs;

    /* cookie support */
    char *cookie;

    /* skip origin check flag */
    nopoll_bool skip_origin_header_check;

    /* network interface to bind to */
    char *_interface;

    /* extra HTTP headers to send during the connection */
    char *extra_headers;
};

#endif
